/*
 * edulisp_interpreter.hpp
 *
 *  Created on: 26.04.2011
 *      Author: xdn
 */

#ifndef EDULISP_INTERPRETER_HPP_
#define EDULISP_INTERPRETER_HPP_

#include <iostream>
#include <list>
#include "edulisp_nametable.hpp"
#include "edulisp.hpp"

using namespace std;

enum InterpreterErrorCode { IEC_OK = 0, IEC_NOTFUNC, IEC_NOARGS, IEC_INVTYPE,
	IEC_UNKNOWNFUNC, IEC_NOTDEFINED, IEC_CONST, IEC_DIVBYZERO, IEC_NOTID,
	IEC_INVARGS, IEC_INTDEFUN, IEC_NORESULT, IEC_INTERNAL };

class ArgumentList : public list<NameTable_Entry*>
{
public:
	~ArgumentList();
	void ClearSublist(ArgumentList::iterator SublistHead, bool ClearAll = false);
	void FindSublist(ArgumentList::iterator& SublistHead,
			unsigned int& ArgumentsCounter);
	void ClearArguments();
};

class LocalWorkspace
{
private:
	LocalVariables LocalVariables_;
	Lexeme Owner_;
	NameTable& NameTable_;
public:
	LocalWorkspace(NameTable& NameTable__, Lexeme Owner = -1);
	LocalWorkspace(NameTable& NameTable__, LocalVariables& Template,
			Lexeme Owner = -1);
	~LocalWorkspace();
	bool BuildWorkspace(LexemeList& LexemeList_);
	NameTable_Entry *GetLocal(Lexeme GlobalVariable);
	NameTable_Entry *Return(NameTable_Entry *LocalVariable);
	NameTable_Entry *SetLocal(Lexeme LocalVariable, NameTable_Entry *Value);
protected:
};


class Interpreter
{
private:
	istream *p_Input;
	ostream *p_Output;
	ArgumentList Arguments;
	NameTable_Entry* PassResult(NameTable_Entry *var);
	bool MathOperation(int& X1, double& X2, NameTable_Entry& val, bool& Float,
			const char MathOperator);
	bool InitMath(int& X1, double& X2, NameTable_Entry& val, bool& Float,
			const char MathOperator);
	InterpreterErrorCode CallFunction(NameTable& NameTable_,
			FunctionDescriptor& FunctionDescriptor_,
			unsigned int ArgumentsNumber, ArgumentList& Arguments,
			ArgumentList::iterator ArgumentsHead, NameTable_Entry*& Result);
	InterpreterErrorCode ExecuteInternal(NameTable& NameTable_,
				unsigned int ArgumentsNumber, ArgumentList& Arguments,
				ArgumentList::iterator ArgumentsHead, NameTable_Entry*& Result);
public:
	Interpreter(istream& Input, ostream& Output);
	~Interpreter();
	InterpreterErrorCode Execute(NameTable& NameTable_,
			FunctionDescriptor& FunctionDescriptor_,
			LocalWorkspace *LocalWorkspace_, NameTable_Entry*& Result);
protected:
};

#endif /* EDULISP_INTERPRETER_HPP_ */
